
#ifndef PICA_DB_TABLE
#define PICA_DB_TABLE
#endif

#include <pica_statdb.hh>
#include "statdb_tb_def.hh"
#include "pica_api/pica_counter_api.hh"


const char *statdb_tb_names_pfx[STATDB_TB_MAX] = {
    "portsCounters_",
    "ofFlowsCounters_"
};

#ifndef STATDB_TB_COLUMN
//#define _STATDB_TB_COLUMN(TB_INDEX, COLUMN_NAME, id, TYPE)
#define STATDB_TB_COLUMN(TB_INDEX, COLUMN_NAME, id, TYPE)
    //_STATDB_TB_COLUMN(TB_INDEX, COLUMN_NAME, id, TYPE)
#endif
//used by SQL to create ports table
#define PORTS_COLUMN_BASIC  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "port", 1, "TEXT PRIMARY KEY"), \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "inBytes", 2, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "outBytes", 3, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "inPkts", 4, "TEXT"),    \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "outPkts", 5, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "inDropPkts", 6, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "outDropPkts", 7, "TEXT"), 
#define CLM_BASIC_NUM 7

#if defined(PRONTO3920s) || defined(PRONTO3920) || !defined(SDK_DEPRECATED_VERSION)
#define PORTS_COLUMN_QUEUE_OUT \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0OutPkts", 8, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1OutPkts", 9, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2OutPkts", 10, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3OutPkts", 11, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4OutPkts", 12, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5OutPkts", 13, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6OutPkts", 14, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7OutPkts", 15, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0OutBytes", 16, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1OutBytes", 17, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2OutBytes", 18, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3OutBytes", 19, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4OutBytes", 20, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5OutBytes", 21, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6OutBytes", 22, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7OutBytes", 23, "TEXT"),
#define CLM_QUEUE_OUT_NUM 16
#elif defined(PRONTO3295)//others then 3920s
#define PORTS_COLUMN_QUEUE_OUT
#define CLM_QUEUE_OUT_NUM 0
#endif

#define PORTS_COLUMN_QUEUE_DROP \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0DropPkts", 24, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1DropPkts", 25, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2DropPkts", 26, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3DropPkts", 27, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4DropPkts", 28, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5DropPkts", 29, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6DropPkts", 30, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7DropPkts", 31, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0DropBytes", 32, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1DropBytes", 33, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2DropBytes", 34, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3DropBytes", 35, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4DropBytes", 36, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5DropBytes", 37, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6DropBytes", 38, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7DropBytes", 39, "TEXT")
#define CLM_QUEUE_DROP_NUM 16

#define STATDB_TB_PORTS_COLUMN PORTS_COLUMN_BASIC \
    PORTS_COLUMN_QUEUE_OUT \
    PORTS_COLUMN_QUEUE_DROP
#define PORTS_CLM_NUM CLM_BASIC_NUM+CLM_QUEUE_OUT_NUM+CLM_QUEUE_DROP_NUM

#define STATDB_TB_OFFLOW_COLUMN  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "flowId", 1, "TEXT PRIMARY KEY"),  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "matchFields", 2, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "matchInPort", 3, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "outPorts", 4, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "receivedBytes", 5, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "queue", 6, "TEXT"),  \
    STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "time", 7, "TEXT")
#define OFFLOW_CLM_NUM 7


#include <pica_port_map.hh> //extern int int pica_uport_to_user_port[];
#include <pica_lcmgr_client.hh>

static int uport;
static usp_t usp_index;
static usp_t usp_array[MAX_PHYSICAL_PORT_NUM+1];

extern bool map_user_port_to_mp(const int user_port, mp_t& mp);
extern bool pica_mp_to_usp(const mp_t& mp, usp_t& usp);

static uint32_t get_ifname_port(string &ifname)
{
    int len;
    int port;

    len = ifname.size();
    if (ifname[len-2] == '/') {
        port = ifname[len-1] - '0';
    } else {
        port = ifname[len-2] - '0';
        port *= 10;
        port += ifname[len-1] -'0';
    }

    return port;
}
/* Make sure we get port's counters from port1(ge-1/1/1),to 
 * portX(ge-1/1/52), and without duplicated ports, so we need 
 * to delete duplicated port(ge-1/1/49), and sort it.*/
static void init_usp_array()
{
    int i;
    mp_t mp;
    usp_t usp;
    string ifname;
    uint32_t port;

    for (i=1; i<=pica_max_line_card_user_port; i++) {
        port = pica_uport_to_user_port[i];
        map_user_port_to_mp(port, mp);
        pica_mp_to_usp(mp, usp);
        usp_to_ifname(ifname, usp);
        usp_array[get_ifname_port(ifname)-1] = usp;
    }
}

static bool port_tb_get_next_portindex()
{
    if (usp_array[uport].port() == 0) {
        uport = 0;
        return false;
    }

    usp_index = usp_array[uport];
    uport++;

    return true;
}

static void port_tb_rest_portindex()
{
    if (usp_array[0].port() == 0)
        init_usp_array();
    uport = 0;
}

#undef STATDB_TB_COLUMN
#define STATDB_TB_COLUMN(TB_INDEX, COLUMN_NAME, id, TYPE) get_##TB_INDEX##_column##id##_value
bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "port", 1, "TEXT PRIMARY KEY")(char *value)
{
    return pica_get_port_name(usp_index, value); 
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "inBytes", 2, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;
    rc = pica_get_port_counter(usp_index, STAT_IF_IN_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "outBytes", 3, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;
    rc = pica_get_port_counter(usp_index, STAT_IF_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "inPkts", 4, "TEXT")(char *column_value)
{
    uint64_t value_nc = 0;
    uint64_t value_c = 0;
    bool rc;

    rc = pica_get_port_counter(usp_index, STAT_IF_IN_NON_UCAST_PKTS, &value_nc);
    rc = pica_get_port_counter(usp_index, STAT_IF_IN_UCAST_PKTS, &value_c);
    if (rc) {
        sprintf(column_value, "%llu", value_nc+value_c);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "outPkts", 5, "TEXT")(char *column_value)
{
    uint64_t value_nc = 0;
    uint64_t value_c = 0;
    bool rc;

    rc = pica_get_port_counter(usp_index, STAT_IF_OUT_NON_UCAST_PKTS, &value_nc);
    rc = pica_get_port_counter(usp_index, STAT_IF_OUT_UCAST_PKTS, &value_c);
    if (rc) {
        sprintf(column_value, "%llu", value_nc+value_c);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "inDropPkts", 6, "TEXT")(char *column_value)
{
    uint64_t value_nc = 0;
    uint64_t value_c = 0;
    bool rc;

    rc = pica_get_port_counter(usp_index, STAT_IF_IN_DISCARDS, &value_nc);
    rc = pica_get_port_counter(usp_index, STAT_IF_IN_ERRORS, &value_c);
    if (rc) {
        sprintf(column_value, "%llu", value_nc+value_c);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "outDropPkts", 7, "TEXT")(char *column_value)
{
    uint64_t value_nc = 0;
    uint64_t value_c = 0;
    bool rc;

    rc = pica_get_port_counter(usp_index, STAT_IF_OUT_DISCARDS, &value_nc);
    rc = pica_get_port_counter(usp_index, STAT_IF_OUT_ERRORS, &value_c);
    if (rc) {
        sprintf(column_value, "%llu", value_nc+value_c);
        return true;
    }

    return false;
}

#if defined(PRONTO3920s) || defined(PRONTO3920) || !defined(SDK_DEPRECATED_VERSION)
bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0OutPkts", 8, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 0, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1OutPkts", 9, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 1, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2OutPkts", 10, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 2, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3OutPkts", 11, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 3, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4OutPkts", 12, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 4, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5OutPkts", 13, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 5, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6OutPkts", 14, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 6, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7OutPkts", 15, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 7, COSQ_STAT_OUT_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0OutBytes", 16, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 0, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1OutBytes", 17, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 1, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2OutBytes", 18, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 2, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3OutBytes", 19, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 3, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4OutBytes", 20, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 4, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5OutBytes", 21, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 5, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6OutBytes", 22, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 6, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7OutBytes", 23, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 7, COSQ_STAT_OUT_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}
#endif

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0DropPkts", 24, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 0, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1DropPkts", 25, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 1, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }\

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2DropPkts", 26, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 2, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3DropPkts", 27, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 3, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4DropPkts", 28, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 4, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}
bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5DropPkts", 29, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 5, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6DropPkts", 30, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 6, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7DropPkts", 31, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 7, COSQ_STAT_DROP_PKTS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q0DropBytes", 32, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 0, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q1DropBytes", 33, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 1, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q2DropBytes", 34, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 2, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q3DropBytes", 35, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 3, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q4DropBytes", 36, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 4, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q5DropBytes", 37, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 5, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q6DropBytes", 38, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 6, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

bool STATDB_TB_COLUMN(STATDB_TB_PORTS, "q7DropBytes", 39, "TEXT")(char *column_value)
{
    uint64_t value = 0;
    bool rc;

    rc = pica_get_port_cosq_counter(usp_index, 7, COSQ_STAT_DROP_OCTETS, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }

    return false;
}

/*ofFlowTable definitions */
typedef struct id_list_ {
    uint32_t id;
    struct id_list_ *next;
} IdList;

extern struct timeval lastStartTimestamp;  //in pica_statdb.hh
extern IdList* get_flowid_list();        //in lcmgr_offlow_table.cc
extern bool get_offlow_column_value(uint32_t id, const char *column_name, char *retvalue);
extern bool ctype_pica_get_of_flow_stat_counter64(const uint32_t id, uint64_t* value);

static IdList *next_flowid;

static bool offlow_tb_get_next_flowid()
{
    if (next_flowid == NULL) {
        next_flowid = get_flowid_list();
    } else {
        next_flowid = next_flowid->next;
    }

    if (next_flowid == NULL) {
        return false;
    } else {
        return true;
    }
}

static void offlow_tb_rest_next_flowid()
{
    next_flowid = NULL;
}

bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "flowId", 1, "TEXT PRIMARY KEY")(char *column_value)
{
    sprintf(column_value, "%lu", next_flowid->id);
    return true;
}
bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "matchFields", 2, "TEXT")(char *column_value)
{
    return get_offlow_column_value(next_flowid->id, "matchFields",column_value);
}
bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "matchInPort", 3, "TEXT")(char *column_value)
{
    return get_offlow_column_value(next_flowid->id, "matchInPort",column_value);
}
bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "outPorts", 4, "TEXT")(char *column_value)
{
    return get_offlow_column_value(next_flowid->id, "outPorts",column_value);
}
bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "receivedBytes", 5, "TEXT")(char *column_value)
{
    uint64_t value;
    bool rc;

    rc = ctype_pica_get_of_flow_stat_counter64(next_flowid->id, &value);
    if (rc) {
        sprintf(column_value, "%llu", value);
        return true;
    }
    return false;
}
bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "queue", 6, "TEXT")(char *column_value)
{
    return get_offlow_column_value(next_flowid->id, "queue", column_value);
}
bool STATDB_TB_COLUMN(STATDB_TB_OFFLOWS, "time", 7, "TEXT")(char *column_value)
{
    struct tm *t;
    t = gmtime(&lastStartTimestamp.tv_sec);
    snprintf(column_value, 40, "%04d-%02d-%02dT%02d:%02d:%02dZ",
            t->tm_year+1900,  t->tm_mon+1, t->tm_mday, t->tm_hour,
            t->tm_min, t->tm_sec);
    return true;
}


#undef STATDB_TB_COLUMN
#define STATDB_TB_COLUMN(TB_INDEX, COLUMN_NAME, id, TYPE) TB_INDEX##_##id 
enum {
    STATDB_TB_PORTS_ID_INDEX=0,
    STATDB_TB_PORTS_COLUMN,
    PORTS_TB_N_COLUMN
};
enum {
    STATDB_TB_OFFLOW_ID_INDEX=0,
    STATDB_TB_OFFLOW_COLUMN,
    OFFLOW_TB_N_COLUMN
};

statdb_tb_info_t port_tb_info = {
    "portsCounters",
    NULL,
    PORTS_TB_N_COLUMN-1,
    port_tb_get_next_portindex,
    port_tb_rest_portindex
};

statdb_tb_info_t offlow_tb_info = {
    "ofFlowCounters",
    NULL,
    OFFLOW_TB_N_COLUMN-1,
    offlow_tb_get_next_flowid,
    offlow_tb_rest_next_flowid
};


//statdb_tb_info_t *p_tb_info[STATDB_TB_MAX] = {
//    //STATDB_TB_PORTS
//    &port_tb_info,
//    //STATDB_TB_OFFLOWS
//    &offlow_tb_info
//};

#undef STATDB_TB_COLUMN
#define STATDB_TB_COLUMN(TB_INDEX, COLUMN_NAME, id, TYPE) {\
    COLUMN_NAME, \
    TB_INDEX##_##id, \
    TYPE, \
    get_##TB_INDEX##_column##id##_value \
    }
statdb_tb_column_t port_tb_column[] = {
    STATDB_TB_PORTS_COLUMN
};

statdb_tb_column_t offlow_tb_column[] = {
    STATDB_TB_OFFLOW_COLUMN
};

//statdb_tb_column_t *p_tb_column[STATDB_TB_MAX] = {
//    port_tb_column,
//    port_tb_column
//    //&offlow_tb_column
//};

